package com.example.controller;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;

/**
 * 通过客户端来操作elasticsearch
 *
 * @author 夏智峰
 * @create 2018-03-12 13:23
 */
@RestController
@RequestMapping("/client")
public class ClientLearnController {
  private static final Logger log = LoggerFactory.getLogger(ClientLearnController.class);
  @Autowired
  private TransportClient client;

  /**
   * @desc 复合查询
   * @author 夏智峰
   * @create 2018/3/12 16:43
   **/
  @GetMapping("/query/{index}/{type}")
  public ResponseEntity query(@PathVariable(value = "index") String index,
                              @PathVariable(value = "type") String type,
                              String author, String title, String sex,
                              @RequestParam(name = "ltWordCount", defaultValue = "0") int ltWordCount,
                              @RequestParam(name = "gtWordCount", defaultValue = "0")int gtWordCount
//                              @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date ltPublishDate,
//                              @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date gtPublishDate
  ) {
    BoolQueryBuilder boolQUery = QueryBuilders.boolQuery();
    if (title != null) {
      boolQUery.must(QueryBuilders.matchQuery("title", title));
    }
    RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("wordCount")
            .from(gtWordCount);
    if (ltWordCount > 0) {
      rangeQuery.to(ltWordCount);
    }

    boolQUery.filter(rangeQuery);

    SearchRequestBuilder builder = client.prepareSearch(index)
            .setTypes(type)
            .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
            .setQuery(boolQUery)
            .setFrom(0)
            .setSize(10);
    log.info(builder.toString());

    SearchResponse response = builder.get();
    List<Map<String, Object>> result = new ArrayList<>();

    response.getHits().forEach(hit -> result.add(hit.getSourceAsMap()));

    return new ResponseEntity(result, HttpStatus.OK);
  }

  /**
   * @desc 根据id读取指定索引
   * @author 夏智峰
   * @create 2018/3/12 15:03
   **/
  @GetMapping("/get/{index}/{type}/{id}")
  public ResponseEntity getEmployeeByIndex(@PathVariable(value = "index") String index,
                                           @PathVariable(value = "type") String type,
                                           @PathVariable(value = "id") String id) {
    GetResponse result = client.prepareGet(index, type, id)
            .get();
    if (StringUtils.isBlank(id)) {
      return new ResponseEntity(HttpStatus.NOT_FOUND);
    }
    if (!result.isExists()) {
      return new ResponseEntity(HttpStatus.NOT_FOUND);
    }
    return new ResponseEntity(result.getSource(), HttpStatus.OK);
  }

  /**
   * @desc 插入数据
   * @author 夏智峰
   * @create 2018/3/12 14:43
   **/
  @PostMapping("/add/{index}/{type}/{id}")
  public ResponseEntity addNovel(@PathVariable(value = "index") String index,
                                 @PathVariable(value = "type") String type,
                                 @PathVariable(value = "id") String id, String title, String author,
                                 int wordCount,
                                 @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date
                                           publishDate, String sex,
                                 String[] test) {
    try {
      Validate.notEmpty(id, "id不能为空");
      Validate.notEmpty(title, "title不能为空");
      Validate.notEmpty(author, "author不能为空");
      Validate.notNull(wordCount, "wordCOunt不能为空");
      Validate.notNull(publishDate, "publishDate不能为空");
      Validate.notEmpty(sex, "sex不能为空");
      Validate.notEmpty(test, "test[]不能为空");
      XContentBuilder builder = jsonBuilder()
              .startObject()
              .field("title", title)
              .field("author", author)
              .field("wordCount", wordCount)
              .field("publishDate", publishDate)
              .field("sex", sex)
              .field("test", test)
              .endObject();

      IndexResponse result = client.prepareIndex(index, type, id)
              .setSource(builder)
              .get();
      return new ResponseEntity(result.getResult().toString(), HttpStatus.OK);
    } catch (Exception e) {
      e.printStackTrace();
      return new ResponseEntity(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  /**
   * @desc 修改指定的文档
   * @author 夏智峰
   * @create 2018/3/12 15:27
   **/
  @PostMapping("/update/{index}/{type}/{id}")
  public ResponseEntity update(@PathVariable(value = "index") String index,
                               @PathVariable(value = "type") String type,
                               @PathVariable(value = "id") String id, String title, String author) {
    UpdateRequest update = new UpdateRequest(index, type, id);
    try {
      XContentBuilder builder = jsonBuilder()
              .startObject();
      if (Objects.nonNull(title)) {
        builder.field("title", title);
      }
      if (Objects.nonNull(author)) {
        builder.field("author", author);
      }
      builder.endObject();

      update.doc(builder);
      UpdateResponse result = client.update(update).get();
      return new ResponseEntity(result.getResult().toString(), HttpStatus.OK);
    } catch (Exception e) {
      e.printStackTrace();
      return new ResponseEntity(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  /**
   * @desc 删除指定的doc
   * @author 夏智峰
   * @create 2018/3/12 14:50
   **/
  @GetMapping("/delete/{index}/{type}/{id}")
  public ResponseEntity delte(@PathVariable(value = "index") String index,
                              @PathVariable(value = "type") String type,
                              @PathVariable(value = "id") String id) {
    DeleteResponse result = client.prepareDelete(index, type, id).get();
    return new ResponseEntity(result.getResult().toString(), HttpStatus.OK);
  }
}
